﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;

using Perseus;
using Perseus.Xml;

using Hetymine.Executioner.Controls;

namespace Hetymine.Executioner.Commands {
    public class HotString : ICommand, IMultiInput {
        private static HotStringCommand _Configurator;
        public HotString() {
            this.Commands = new List<CommandInfo>();
            this.Name = string.Empty;

            this.Inputs = new List<string>(new string[] { "string", "audio" });
            this.EnabledInputs = new List<string>(new string[] { "string" });
        }        
        
        public List<CommandInfo> Commands { get; set; }

        #region IMultiInput Members
        public List<string> Inputs { get; protected set; }
        public List<string> EnabledInputs { get; protected set; }
        public void EnableInput(string input) {
            if (this.Inputs.Contains(input)) {
                if (!this.EnabledInputs.Contains(input)) {
                    this.EnabledInputs.Add(input);
                }
            }
        }
        public void DisableInput(string input) {
            this.EnabledInputs.Remove(input);
        }
        #endregion

        public string Name { get; set; }
        public bool Execute(string parameters) {
            bool success = true;
            
            foreach (CommandInfo c in this.Commands) {
                if (!Executioner.ExecuteProcessCommand(c.Command, c.Arguments)) {
                    success = false;
                }
            }

            return success;
        }

        public void Load(XElement element) {
            this.Name = element.Element("Name").ValueOrEmpty();
            this.Commands = Helper.Commands(element);
            
            this.EnabledInputs = Helper.Inputs(element.Attribute("Inputs"), this.Inputs.ToArray());
        }
        public XElement Save() {
            if (this.IsEmpty) {
                throw new Exception("Cannot save empty hot string.");
            }

            XElement xe = new XElement("HotString");
            string inputs = this.EnabledInputs.ToArray().Join(",");
            if (inputs != "string") {
                xe.Add(new XAttribute("Inputs", inputs));
            }

            xe.Add(new XElement("Name", this.Name));

            foreach (CommandInfo ci in this.Commands) {
                XElement cmd = new XElement("Command", ci.Command);
                if (ci.Arguments != string.Empty) {
                    cmd.Add(new XAttribute("Args", ci.Arguments));
                }
                xe.Add(cmd);
            }

            return xe;
        }
        public bool IsEmpty {
            get { return (this.Name == string.Empty); }
        }

        public ICommandConfigurator<ICommand> Configurator {
            get {
                if (HotString._Configurator == null) {
                    HotString._Configurator = new HotStringCommand();
                }
                HotString._Configurator.InitializeConfig(this);
                return HotString._Configurator;
            }
        }

        public override string ToString() {
            if (this.Name == string.Empty) {
                return string.Empty;
            }

            string s = this.Name;

            if (this.EnabledInputs.Contains("audio")) {
                if (this.EnabledInputs.Contains("string")) {
                    s += " (string, audio)";
                }
                else {
                    s += " (audio)";
                }
            }

            return s;
        }

        public object Clone() {
            HotString hs = (HotString)this.MemberwiseClone();
            hs.Commands = new List<CommandInfo>();
            foreach (CommandInfo ci in this.Commands) {
                hs.Commands.Add(new CommandInfo(ci.Command, ci.Arguments));
            }
            return hs;

            hs.Inputs = new List<string>();
            foreach (string s in this.Inputs) {
                hs.Inputs.Add(s);
            }

            return hs;
        }
    }
}
